home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 151 / cd-rom 151.iso / internet / firefox / Firefox Setup 3.0 Beta 1.exe / nonlocalized / components / FeedConverter.js < prev    next >
Encoding:
Text File  |  2007-11-09  |  21.3 KB  |  663 lines

  1. //@line 38 "e:\builds\tinderbox\Fx-Rel\WINNT_5.2_Depend\mozilla\browser\components\feeds\src\FeedConverter.js"
  2.  
  3. const Cc = Components.classes;
  4. const Ci = Components.interfaces;
  5. const Cr = Components.results;
  6.  
  7. function LOG(str) {
  8.   dump("*** " + str + "\n");
  9. }
  10.  
  11. const FC_CLASSID = Components.ID("{229fa115-9412-4d32-baf3-2fc407f76fb1}");
  12. const FC_CLASSNAME = "Feed Stream Converter";
  13. const FS_CLASSID = Components.ID("{2376201c-bbc6-472f-9b62-7548040a61c6}");
  14. const FS_CLASSNAME = "Feed Result Service";
  15. const FS_CONTRACTID = "@mozilla.org/browser/feeds/result-service;1";
  16. const FPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=feed";
  17. const FPH_CLASSID = Components.ID("{4f91ef2e-57ba-472e-ab7a-b4999e42d6c0}");
  18. const FPH_CLASSNAME = "Feed Protocol Handler";
  19. const PCPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=pcast";
  20. const PCPH_CLASSID = Components.ID("{1c31ed79-accd-4b94-b517-06e0c81999d5}");
  21. const PCPH_CLASSNAME = "Podcast Protocol Handler";
  22.  
  23. const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
  24. const TYPE_ANY = "*/*";
  25.  
  26. const FEEDHANDLER_URI = "about:feeds";
  27.  
  28. const PREF_SELECTED_APP = "browser.feeds.handlers.application";
  29. const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
  30. const PREF_SELECTED_ACTION = "browser.feeds.handler";
  31. const PREF_SELECTED_READER = "browser.feeds.handler.default";
  32.  
  33. function safeGetCharPref(pref, defaultValue) {
  34.   var prefs =   
  35.       Cc["@mozilla.org/preferences-service;1"].
  36.       getService(Ci.nsIPrefBranch);
  37.   try {
  38.     return prefs.getCharPref(pref);
  39.   }
  40.   catch (e) {
  41.   }
  42.   return defaultValue;
  43. }
  44.  
  45. function FeedConverter() {
  46. }
  47. FeedConverter.prototype = {
  48.   /**
  49.    * This is the downloaded text data for the feed.
  50.    */
  51.   _data: null,
  52.   
  53.   /**
  54.    * This is the object listening to the conversion, which is ultimately the
  55.    * docshell for the load.
  56.    */
  57.   _listener: null,
  58.  
  59.   /**
  60.    * Records if the feed was sniffed
  61.    */
  62.   _sniffed: false,
  63.   
  64.   /**
  65.    * See nsIStreamConverter.idl
  66.    */
  67.   canConvert: function FC_canConvert(sourceType, destinationType) {
  68.     // We only support one conversion.
  69.     return destinationType == TYPE_ANY && sourceType == TYPE_MAYBE_FEED;
  70.   },
  71.   
  72.   /**
  73.    * See nsIStreamConverter.idl
  74.    */
  75.   convert: function FC_convert(sourceStream, sourceType, destinationType, 
  76.                                context) {
  77.     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  78.   },
  79.   
  80.   /**
  81.    * See nsIStreamConverter.idl
  82.    */
  83.   asyncConvertData: function FC_asyncConvertData(sourceType, destinationType,
  84.                                                  listener, context) {
  85.     this._listener = listener;
  86.   },
  87.   
  88.   /**
  89.    * Whether or not the preview page is being forced.
  90.    */
  91.   _forcePreviewPage: false,
  92.   
  93.   /** 
  94.    * Release our references to various things once we're done using them.
  95.    */
  96.   _releaseHandles: function FC__releaseHandles() {
  97.     this._listener = null;
  98.     this._request = null;
  99.     this._processor = null;
  100.   },
  101.   
  102.   /**
  103.    * See nsIFeedResultListener.idl
  104.    */
  105.   handleResult: function FC_handleResult(result) {
  106.     // Feeds come in various content types, which our feed sniffer coerces to
  107.     // the maybe.feed type. However, feeds are used as a transport for 
  108.     // different data types, e.g. news/blogs (traditional feed), video/audio
  109.     // (podcasts) and photos (photocasts, photostreams). Each of these is 
  110.     // different in that there's a different class of application suitable for
  111.     // handling feeds of that type, but without a content-type differentiation
  112.     // it is difficult for us to disambiguate.
  113.     // 
  114.     // The other problem is that if the user specifies an auto-action handler
  115.     // for one feed application, the fact that the content type is shared means 
  116.     // that all other applications will auto-load with that handler too, 
  117.     // regardless of the content-type. 
  118.     //
  119.     // This means that content-type alone is not enough to determine whether
  120.     // or not a feed should be auto-handled. This means that for feeds we need
  121.     // to always use this stream converter, even when an auto-action is 
  122.     // specified, not the basic one provided by WebContentConverter. This 
  123.     // converter needs to consume all of the data and parse it, and based on
  124.     // that determination make a judgement about type. 
  125.     //
  126.     // Since there are no content types for this content, and I'm not going to
  127.     // invent any, the upshot is that while a user can set an auto-handler for
  128.     // generic feed content, the system will prevent them from setting an auto-
  129.     // handler for other stream types. In those cases, the user will always see
  130.     // the preview page and have to select a handler. We can guess and show 
  131.     // a client handler, but will not be able to show web handlers for those
  132.     // types.
  133.     //
  134.     // If this is just a feed, not some kind of specialized application, then
  135.     // auto-handlers can be set and we should obey them. 
  136.     try {
  137.       var feedService = 
  138.           Cc["@mozilla.org/browser/feeds/result-service;1"].
  139.           getService(Ci.nsIFeedResultService);
  140.       if (!this._forcePreviewPage && result.doc) {
  141.         var handler = safeGetCharPref(PREF_SELECTED_ACTION, "ask");
  142.         if (handler != "ask") {
  143.           if (handler == "reader")
  144.             handler = safeGetCharPref(PREF_SELECTED_READER, "bookmarks");
  145.           switch (handler) {
  146.             case "web":
  147.               var wccr = 
  148.                   Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
  149.                   getService(Ci.nsIWebContentConverterService);
  150.               var feed = result.doc.QueryInterface(Ci.nsIFeed);
  151.               if (feed.type == Ci.nsIFeed.TYPE_FEED &&
  152.                   wccr.getAutoHandler(TYPE_MAYBE_FEED)) {
  153.                 wccr.loadPreferredHandler(this._request);
  154.                 return;
  155.               }
  156.               break;
  157.  
  158.             default:
  159.               LOG("unexpected handler: " + handler);
  160.               // fall through -- let feed service handle error
  161.             case "bookmarks":
  162.             case "client":
  163.               try {
  164.                 var feed = result.doc.QueryInterface(Ci.nsIFeed);
  165.                 var title = feed.title ? feed.title.plainText() : "";
  166.                 var desc = feed.subtitle ? feed.subtitle.plainText() : "";
  167.                 feedService.addToClientReader(result.uri.spec, title, desc);
  168.                 return;
  169.               } catch(ex) { /* fallback to preview mode */ }
  170.           }
  171.         }
  172.       }
  173.           
  174.       var ios = 
  175.           Cc["@mozilla.org/network/io-service;1"].
  176.           getService(Ci.nsIIOService);
  177.       var chromeChannel;
  178.  
  179.       // show the feed page if it wasn't sniffed and we have a document,
  180.       // or we have a document, title, and link or id
  181.       if (result.doc && (!this._sniffed ||
  182.           (result.doc.title && (result.doc.link || result.doc.id)))) {
  183.  
  184.         // If there was no automatic handler, or this was a podcast,
  185.         // photostream or some other kind of application, we must always
  186.         // show the preview page.
  187.         
  188.         // Store the result in the result service so that the display
  189.         // page can access it.
  190.  
  191.         feedService.addFeedResult(result);
  192.  
  193.         // Now load the actual XUL document.
  194.         var chromeURI = ios.newURI(FEEDHANDLER_URI, null, null);
  195.         chromeChannel = ios.newChannelFromURI(chromeURI, null);
  196.         chromeChannel.originalURI = result.uri;
  197.       }
  198.       else
  199.         chromeChannel = ios.newChannelFromURI(result.uri, null);
  200.  
  201.       chromeChannel.loadGroup = this._request.loadGroup;
  202.       chromeChannel.asyncOpen(this._listener, null);
  203.     }
  204.     finally {
  205.       this._releaseHandles();
  206.     }
  207.   },
  208.   
  209.   /**
  210.    * See nsIStreamListener.idl
  211.    */
  212.   onDataAvailable: function FC_onDataAvailable(request, context, inputStream, 
  213.                                                sourceOffset, count) {
  214.     if (this._processor)
  215.       this._processor.onDataAvailable(request, context, inputStream,
  216.                                       sourceOffset, count);
  217.   },
  218.   
  219.   /**
  220.    * See nsIRequestObserver.idl
  221.    */
  222.   onStartRequest: function FC_onStartRequest(request, context) {
  223.     var channel = request.QueryInterface(Ci.nsIChannel);
  224.  
  225.     // Check for a header that tells us there was no sniffing
  226.     // The value doesn't matter.
  227.     try {
  228.       var httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
  229.       var noSniff = httpChannel.getResponseHeader("X-Moz-Is-Feed");
  230.     }
  231.     catch (ex) {
  232.       this._sniffed = true;
  233.     }
  234.  
  235.     this._request = request;
  236.     
  237.     // Save and reset the forced state bit early, in case there's some kind of
  238.     // error.
  239.     var feedService = 
  240.         Cc["@mozilla.org/browser/feeds/result-service;1"].
  241.         getService(Ci.nsIFeedResultService);
  242.     this._forcePreviewPage = feedService.forcePreviewPage;
  243.     feedService.forcePreviewPage = false;
  244.  
  245.     // Parse feed data as it comes in
  246.     this._processor =
  247.         Cc["@mozilla.org/feed-processor;1"].
  248.         createInstance(Ci.nsIFeedProcessor);
  249.     this._processor.listener = this;
  250.     this._processor.parseAsync(null, channel.URI);
  251.     
  252.     this._processor.onStartRequest(request, context);
  253.   },
  254.   
  255.   /**
  256.    * See nsIRequestObserver.idl
  257.    */
  258.   onStopRequest: function FC_onStopReqeust(request, context, status) {
  259.     if (this._processor)
  260.       this._processor.onStopRequest(request, context, status);
  261.   },
  262.   
  263.   /**
  264.    * See nsISupports.idl
  265.    */
  266.   QueryInterface: function FC_QueryInterface(iid) {
  267.     if (iid.equals(Ci.nsIFeedResultListener) ||
  268.         iid.equals(Ci.nsIStreamConverter) ||
  269.         iid.equals(Ci.nsIStreamListener) ||
  270.         iid.equals(Ci.nsIRequestObserver)||
  271.         iid.equals(Ci.nsISupports))
  272.       return this;
  273.     throw Cr.NS_ERROR_NO_INTERFACE;
  274.   },
  275. };
  276.  
  277. var FeedConverterFactory = {
  278.   createInstance: function FS_createInstance(outer, iid) {
  279.     if (outer != null)
  280.       throw Cr.NS_ERROR_NO_AGGREGATION;
  281.     return new FeedConverter().QueryInterface(iid);
  282.   },
  283.  
  284.   QueryInterface: function FS_QueryInterface(iid) {
  285.     if (iid.equals(Ci.nsIFactory) ||
  286.         iid.equals(Ci.nsISupports))
  287.       return this;
  288.     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  289.   },
  290. };
  291.  
  292. /**
  293.  * Keeps parsed FeedResults around for use elsewhere in the UI after the stream
  294.  * converter completes. 
  295.  */
  296. var FeedResultService = {
  297.   
  298.   /**
  299.    * A URI spec -> [nsIFeedResult] hash. We have to keep a list as the
  300.    * value in case the same URI is requested concurrently.
  301.    */
  302.   _results: { },
  303.   
  304.   /**
  305.    * See nsIFeedService.idl
  306.    */
  307.   forcePreviewPage: false,
  308.   
  309.   /**
  310.    * See nsIFeedService.idl
  311.    */
  312.   addToClientReader: function FRS_addToClientReader(spec, title, subtitle) {
  313.     var prefs =   
  314.         Cc["@mozilla.org/preferences-service;1"].
  315.         getService(Ci.nsIPrefBranch);
  316.  
  317.     var handler = safeGetCharPref(PREF_SELECTED_ACTION, "bookmarks");
  318.     if (handler == "ask" || handler == "reader")
  319.       handler = safeGetCharPref(PREF_SELECTED_READER, "bookmarks");
  320.  
  321.     switch (handler) {
  322.     case "client":
  323.       var clientApp = prefs.getComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile);
  324.  
  325.       // For the benefit of applications that might know how to deal with more
  326.       // URLs than just feeds, send feed: URLs in the following format:
  327.       //
  328.       // http urls: replace scheme with feed, e.g.
  329.       // http://foo.com/index.rdf -> feed://foo.com/index.rdf
  330.       // other urls: prepend feed: scheme, e.g.
  331.       // https://foo.com/index.rdf -> feed:https://foo.com/index.rdf
  332.       var ios = 
  333.           Cc["@mozilla.org/network/io-service;1"].
  334.           getService(Ci.nsIIOService);
  335.       var feedURI = ios.newURI(spec, null, null);
  336.       if (feedURI.schemeIs("http")) {
  337.         feedURI.scheme = "feed";
  338.         spec = feedURI.spec;
  339.       }
  340.       else
  341.         spec = "feed:" + spec;
  342.  
  343.       var ss = 
  344.           Cc["@mozilla.org/browser/shell-service;1"].
  345.           getService(Ci.nsIShellService);
  346.       ss.openApplicationWithURI(clientApp, spec);
  347.       break;
  348.  
  349.     default:
  350.       // "web" should have been handled elsewhere
  351.       LOG("unexpected handler: " + handler);
  352.       // fall through
  353.     case "bookmarks":
  354.       var wm = 
  355.           Cc["@mozilla.org/appshell/window-mediator;1"].
  356.           getService(Ci.nsIWindowMediator);
  357.       var topWindow = wm.getMostRecentWindow("navigator:browser");
  358.       topWindow.PlacesCommandHook.addLiveBookmark(spec, title, subtitle);
  359.       break;
  360.     }
  361.   },
  362.   
  363.   /**
  364.    * See nsIFeedService.idl
  365.    */
  366.   addFeedResult: function FRS_addFeedResult(feedResult) {
  367.     NS_ASSERT(feedResult.uri != null, "null URI!");
  368.     NS_ASSERT(feedResult.uri != null, "null feedResult!");
  369.     var spec = feedResult.uri.spec;
  370.     if(!this._results[spec])  
  371.       this._results[spec] = [];
  372.     this._results[spec].push(feedResult);
  373.   },
  374.   
  375.   /**
  376.    * See nsIFeedService.idl
  377.    */
  378.   getFeedResult: function RFS_getFeedResult(uri) {
  379.     NS_ASSERT(uri != null, "null URI!");
  380.     var resultList = this._results[uri.spec];
  381.     for (var i in resultList) {
  382.       if (resultList[i].uri == uri)
  383.         return resultList[i];
  384.     }
  385.     return null;
  386.   },
  387.   
  388.   /**
  389.    * See nsIFeedService.idl
  390.    */
  391.   removeFeedResult: function FRS_removeFeedResult(uri) {
  392.     NS_ASSERT(uri != null, "null URI!");
  393.     var resultList = this._results[uri.spec];
  394.     if (!resultList)
  395.       return;
  396.     var deletions = 0;
  397.     for (var i = 0; i < resultList.length; ++i) {
  398.       if (resultList[i].uri == uri) {
  399.         delete resultList[i];
  400.         ++deletions;
  401.       }
  402.     }
  403.     
  404.     // send the holes to the end
  405.     resultList.sort();
  406.     // and trim the list
  407.     resultList.splice(resultList.length - deletions, deletions);
  408.     if (resultList.length == 0)
  409.       delete this._results[uri.spec];
  410.   },
  411.  
  412.   createInstance: function FRS_createInstance(outer, iid) {
  413.     if (outer != null)
  414.       throw Cr.NS_ERROR_NO_AGGREGATION;
  415.     return this.QueryInterface(iid);
  416.   },
  417.   
  418.   QueryInterface: function FRS_QueryInterface(iid) {
  419.     if (iid.equals(Ci.nsIFeedResultService) ||
  420.         iid.equals(Ci.nsIFactory) ||
  421.         iid.equals(Ci.nsISupports))
  422.       return this;
  423.     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  424.   },
  425. };
  426.  
  427. /**
  428.  * A protocol handler that converts the URIs of Apple's various bogo protocol
  429.  * schemes into http, as they should be. Mostly, this object just forwards 
  430.  * things through to the HTTP protocol handler.
  431.  */
  432. function FeedProtocolHandler(scheme) {
  433.   this._scheme = scheme;
  434.   var ios = 
  435.       Cc["@mozilla.org/network/io-service;1"].
  436.       getService(Ci.nsIIOService);
  437.   this._http = ios.getProtocolHandler("http");
  438. }
  439. FeedProtocolHandler.prototype = {
  440.   _scheme: "",
  441.   get scheme() {
  442.     return this._scheme;
  443.   },
  444.   
  445.   get protocolFlags() {
  446.     return this._http.protocolFlags;
  447.   },
  448.   
  449.   get defaultPort() {
  450.     return this._http.defaultPort;
  451.   },
  452.   
  453.   allowPort: function FPH_allowPort(port, scheme) {
  454.     return this._http.allowPort(port, scheme);
  455.   },
  456.   
  457.   newURI: function FPH_newURI(spec, originalCharset, baseURI) {
  458.     var uri = 
  459.         Cc["@mozilla.org/network/standard-url;1"].
  460.         createInstance(Ci.nsIStandardURL);
  461.     uri.init(Ci.nsIStandardURL.URLTYPE_STANDARD, 80, spec, originalCharset,
  462.              baseURI);
  463.     return uri;
  464.   },
  465.   
  466.   newChannel: function FPH_newChannel(uri) {
  467.     var ios = 
  468.         Cc["@mozilla.org/network/io-service;1"].
  469.         getService(Ci.nsIIOService);
  470.     // feed: URIs either start feed://, in which case the real scheme is http:
  471.     // or feed:http(s)://, (which by now we've changed to feed://realscheme//)
  472.     const httpsChunk = "feed://https//";
  473.     const httpChunk = "feed://http//";
  474.     if (uri.spec.substr(0, httpsChunk.length) == httpsChunk)
  475.       uri.spec = "https://" + uri.spec.substr(httpsChunk.length);
  476.     else if (uri.spec.substr(0, httpChunk.length) == httpChunk)
  477.       uri.spec = "http://" + uri.spec.substr(httpChunk.length);
  478.     else
  479.       uri.scheme = "http";
  480.  
  481.     var channel =
  482.       ios.newChannelFromURI(uri, null).QueryInterface(Ci.nsIHttpChannel);
  483.     // Set this so we know this is supposed to be a feed
  484.     channel.setRequestHeader("X-Moz-Is-Feed", "1", false);
  485.     channel.originalURI = uri;
  486.     return channel;
  487.   },
  488.   
  489.   QueryInterface: function FPH_QueryInterface(iid) {
  490.     if (iid.equals(Ci.nsIProtocolHandler) ||
  491.         iid.equals(Ci.nsISupports))
  492.       return this;
  493.     throw Cr.NS_ERROR_NO_INTERFACE;
  494.   }  
  495. };
  496.  
  497. var Module = {
  498.   QueryInterface: function M_QueryInterface(iid) {
  499.     if (iid.equals(Ci.nsIModule) ||
  500.         iid.equals(Ci.nsISupports))
  501.       return this;
  502.     throw Cr.NS_ERROR_NO_INTERFACE;
  503.   },
  504.   
  505.   getClassObject: function M_getClassObject(cm, cid, iid) {
  506.     if (!iid.equals(Ci.nsIFactory))
  507.       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  508.     
  509.     if (cid.equals(FS_CLASSID))
  510.       return FeedResultService;
  511.     if (cid.equals(FPH_CLASSID))
  512.       return new GenericComponentFactory(FeedProtocolHandler, "feed");
  513.     if (cid.equals(PCPH_CLASSID))
  514.       return new GenericComponentFactory(FeedProtocolHandler, "pcast");
  515.     if (cid.equals(FC_CLASSID))
  516.       return new GenericComponentFactory(FeedConverter);
  517.       
  518.     throw Cr.NS_ERROR_NO_INTERFACE;
  519.   },
  520.   
  521.   registerSelf: function M_registerSelf(cm, file, location, type) {
  522.     var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
  523.     
  524.     cr.registerFactoryLocation(FS_CLASSID, FS_CLASSNAME, FS_CONTRACTID,
  525.                                file, location, type);
  526.     cr.registerFactoryLocation(FPH_CLASSID, FPH_CLASSNAME, FPH_CONTRACTID,
  527.                                file, location, type);
  528.     cr.registerFactoryLocation(PCPH_CLASSID, PCPH_CLASSNAME, PCPH_CONTRACTID,
  529.                                file, location, type);
  530.  
  531.     // The feed converter is always attached, since parsing must be done to 
  532.     // determine whether or not auto-handling can occur. 
  533.     const converterPrefix = "@mozilla.org/streamconv;1?from=";
  534.     var converterContractID = 
  535.         converterPrefix + TYPE_MAYBE_FEED + "&to=" + TYPE_ANY;
  536.     cr.registerFactoryLocation(FC_CLASSID, FC_CLASSNAME, converterContractID,
  537.                                file, location, type);
  538.   },
  539.   
  540.   unregisterSelf: function M_unregisterSelf(cm, location, type) {
  541.     var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
  542.     cr.unregisterFactoryLocation(FPH_CLASSID, location);
  543.     cr.unregisterFactoryLocation(PCPH_CLASSID, location);
  544.   },
  545.   
  546.   canUnload: function M_canUnload(cm) {
  547.     return true;
  548.   }
  549. };
  550.  
  551. function NSGetModule(cm, file) {
  552.   return Module;
  553. }
  554.  
  555. //@line 44 "e:\builds\tinderbox\Fx-Rel\WINNT_5.2_Depend\mozilla\toolkit\content\debug.js"
  556.  
  557. var gTraceOnAssert = true;
  558.  
  559. /**
  560.  * This function provides a simple assertion function for JavaScript.
  561.  * If the condition is true, this function will do nothing.  If the
  562.  * condition is false, then the message will be printed to the console
  563.  * and an alert will appear showing a stack trace, so that the (alpha
  564.  * or nightly) user can file a bug containing it.  For future enhancements, 
  565.  * see bugs 330077 and 330078.
  566.  *
  567.  * To suppress the dialogs, you can run with the environment variable
  568.  * XUL_ASSERT_PROMPT set to 0 (if unset, this defaults to 1).
  569.  *
  570.  * @param condition represents the condition that we're asserting to be
  571.  *                  true when we call this function--should be
  572.  *                  something that can be evaluated as a boolean.
  573.  * @param message   a string to be displayed upon failure of the assertion
  574.  */
  575.  
  576. function NS_ASSERT(condition, message) {
  577.   if (condition)
  578.     return;
  579.  
  580.   var releaseBuild = true;
  581.   var defB = Components.classes["@mozilla.org/preferences-service;1"]
  582.                        .getService(Components.interfaces.nsIPrefService)
  583.                        .getDefaultBranch(null);
  584.   try {
  585.     switch (defB.getCharPref("app.update.channel")) {
  586.       case "nightly":
  587.       case "beta":
  588.       case "default":
  589.         releaseBuild = false;
  590.     }
  591.   } catch(ex) {}
  592.  
  593.   var caller = arguments.callee.caller;
  594.   var assertionText = "ASSERT: " + message + "\n";
  595.  
  596.   if (releaseBuild) {
  597.     // Just report the error to the console
  598.     Components.utils.reportError(assertionText);
  599.     return;
  600.   }
  601.  
  602.   // Otherwise, dump to stdout and launch an assertion failure dialog
  603.   dump(assertionText);
  604.  
  605.   var stackText = "";
  606.   if (gTraceOnAssert) {
  607.     stackText = "Stack Trace: \n";
  608.     var count = 0;
  609.     while (caller) {
  610.       stackText += count++ + ":" + caller.name + "(";
  611.       for (var i = 0; i < caller.arguments.length; ++i) {
  612.         var arg = caller.arguments[i];
  613.         stackText += arg;
  614.         if (i < caller.arguments.length - 1)
  615.           stackText += ",";
  616.       }
  617.       stackText += ")\n";
  618.       caller = caller.arguments.callee.caller;
  619.     }
  620.   }
  621.  
  622.   var environment = Components.classes["@mozilla.org/process/environment;1"].
  623.                     getService(Components.interfaces.nsIEnvironment);
  624.   if (environment.exists("XUL_ASSERT_PROMPT") &&
  625.       !parseInt(environment.get("XUL_ASSERT_PROMPT")))
  626.     return;
  627.  
  628.   var source = null;
  629.   if (this.window)
  630.     source = window;
  631.   var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
  632.            getService(Components.interfaces.nsIPromptService);
  633.   ps.alert(source, "Assertion Failed", assertionText + stackText);
  634. }
  635. //@line 37 "e:\builds\tinderbox\Fx-Rel\WINNT_5.2_Depend\mozilla\browser\components\feeds\src\GenericFactory.js"
  636.  
  637. /**
  638.  * An object implementing nsIFactory that can construct other objects upon
  639.  * createInstance, passing a set of parameters to that object's constructor.
  640.  */
  641. function GenericComponentFactory(ctor, params) {
  642.   this._ctor = ctor;
  643.   this._params = params;
  644. }
  645. GenericComponentFactory.prototype = {
  646.   _ctor: null,
  647.   _params: null,
  648.   
  649.   createInstance: function GCF_createInstance(outer, iid) {
  650.     if (outer != null)
  651.       throw Cr.NS_ERROR_NO_AGGREGATION;
  652.     return (new this._ctor(this._params)).QueryInterface(iid);
  653.   },
  654.   
  655.   QueryInterface: function GCF_QueryInterface(iid) {
  656.     if (iid.equals(Ci.nsIFactory) ||
  657.         iid.equals(Ci.nsISupports)) 
  658.       return this;
  659.     throw Cr.NS_ERROR_NO_INTERFACE;
  660.   }
  661. };
  662.  
  663.